#!/bin/bash
# 依赖：vim sed uuidgen jq
set -e

function print_definition {
    cat << EOF
{
    "type": "function",
    "function": {
        "name": "replace_in_file",
        "description": "替换选定文件中的内容",
        "parameters": {
            "type": "object",
            "properties": {
                "path": {
                    "type": "string",
                    "description": "目标文件"
                },
                "search_text": {
                    "type": "string",
                    "description": "旧内容"
                },
                "replace_text": {
                    "type": "string",
                    "description": "新内容"
                },
                "replace_all": {
                    "type": "boolean",
                    "description": "替换所有匹配的内容"
                }
            },
            "required": ["path", "search_text", "replace_text"]
        }
    }
}
EOF
    exit
}

function print_system {
    cat << EOF
### replace_in_file 工具规则
- 在\`path\`文件中查找\`search_text\`并替换成\`replace_text\`内容
- 当找到多个匹配项时若\`replace_all == true\`则替换所有匹配内容，否则报匹配冲突错误
- 编辑文件请直接调用工具修改文件，调用前后不用通知用户
- 修改文件前先读取文件，获取最新的文件变化
- 修改文件优先考虑匹配替换，无法匹配替换时再用全文覆盖
- 生成文件后必须写入文件
EOF
    exit
}

if [ $# -gt 0 ]; then
    if [ "$1" = '--help' ]; then
        print_system
    elif [ "$1" = '-h' ]; then
        print_system
    elif [ "$1" = '--usage' ]; then
        print_definition
    elif [ "$1" = '-?' ]; then
        print_definition
    fi
fi

if [ $# -eq 0 ]; then
    exit 1
fi

path=$(echo "$1" | jq -r '.path')
search_text=$(echo "$1" | jq -r '.search_text')
replace_text=$(echo "$1" | jq -r '.replace_text')
replace_all=$(echo "$1" | jq -r '.replace_all')

tmp_path="/tmp/$(uuidgen).$(basename "$path")"
cp "$path" "$tmp_path"

# grep没找到报错
match_count=$(grep -o "$search_text" "$path" | wc -l)
if [ $match_count -lt 1 ]; then
    echo "No match found for search_text" 1>&2
    exit 1
fi
# 匹配冲突报错
if [ "$replace_all" != "true" ]; then
    if [ $match_count -gt 1 ]; then
        echo "More than 1 matches found for search_text" 1>&2
        exit 1
    fi
fi
echo $search_text $replace_text

search_text=$(echo "$search_text" | sed 's_\\_\\\\_g' | sed 's_/_\/_g')
replace_text=$(echo "$replace_text" | sed 's_\\_\\\\_g' | sed 's_/_\/_g')
sed -i "s/$search_text/$replace_text/g" "$tmp_path"

vim -d "$tmp_path" "$path"
while true; do
    echo -n 'accept this file? ('d' to show diff) [y/n/D]: '
    read -sn1 ans
    echo
    if [ "$ans" = 'y' ]; then
        mv "$tmp_path" "$path"
        echo "success" 1>&2
        exit
    elif [ "$ans" = 'n' ]; then
        echo "rejected" 1>&2
        exit
    fi
    vim -d "$tmp_path" "$path"
done
